

#include "HeaderFiles.h"


STR_INFRARED  infraredHdl[4];


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void infrared_timer_init(void)
{

    timer_parameter_struct timer_initpara;
    rcu_periph_clock_enable(RCU_TIMER6);
    timer_deinit(TIMER6);
    
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 60000 - 1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER6,&timer_initpara);
	
	#if 0
	nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
	nvic_irq_enable(TIMER6_IRQn, 0, 1);
	timer_interrupt_enable(TIMER6, TIMER_INT_UP);
	#endif
    
    timer_auto_reload_shadow_enable(TIMER6);
    
    timer_enable(TIMER6);
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void infrared_gpio_init(void)
{
	rcu_periph_clock_enable(RCU_AF);
	rcu_periph_clock_enable(RCU_GPIOF);
	
	#if 0
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
	#endif
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
	gpio_init(GPIOF, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
	
	
	nvic_irq_enable(EXTI2_IRQn, 2U, 0U);  
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOF, GPIO_PIN_SOURCE_2);
	exti_init(EXTI_2, EXTI_INTERRUPT, EXTI_TRIG_BOTH); 
	exti_interrupt_flag_clear(EXTI_2);  
	
	nvic_irq_enable(EXTI3_IRQn, 3U, 0U);  
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOF, GPIO_PIN_SOURCE_3);
	exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_BOTH); 
	exti_interrupt_flag_clear(EXTI_3);  
	
	nvic_irq_enable(EXTI4_IRQn, 4U, 0U);  
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOF, GPIO_PIN_SOURCE_4);
	exti_init(EXTI_4, EXTI_INTERRUPT, EXTI_TRIG_BOTH); 
	exti_interrupt_flag_clear(EXTI_4);  
	
	nvic_irq_enable(EXTI5_9_IRQn, 5U, 0U);  
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOF, GPIO_PIN_SOURCE_5);
	exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_BOTH); 
	exti_interrupt_flag_clear(EXTI_5);  
	
	
	
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void infrared_receive_init(void)
{
	infrared_timer_init();
	infrared_gpio_init();
}




/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
ENUM_INFRARED pulse_value_identify(int16_t pulse_width)
{
	ENUM_INFRARED pulse_value = PULSE_INVALID;

	if((pulse_width > BOOT_CODE_LENGTH_MIN_US) && (pulse_width < BOOT_CODE_LENGTH_MAX_US))
	{
		pulse_value = BOOT_CODE;
	}
	
	else if((pulse_width > BOOL_HIGH_LENGTH_MIN_US) && (pulse_width < BOOL_HIGH_LENGTH_MAX_US))
	{
		pulse_value = BOOL_HIGHT;
	}
	
	else if((pulse_width > BOOL_LOW_LENGTH_MIN_US) && (pulse_width < BOOL_LOW_LENGTH_MAX_US))
	{
		pulse_value = BOOL_LOW;
	}

	return pulse_value;
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
uint8_t infrared_area_analysis(STR_INFRARED *hdl)
{
	#if 0
	uint64_t time_erro = 0;
	
	time_erro = hdl->timestamp_now - hdl->timestamp_old;
	
	if(time_erro < AREA_COVER_REC_TIME)
	{
		uint8_t area_code_sum = 0;
		
		area_code_sum = (hdl->valid_value.half.trueform | hdl->trueform_history[2] | hdl->trueform_history[1] | hdl->trueform_history[0]);
		
		if((area_code_sum == INFRARED_AREA_NUM_E) || (area_code_sum == INFRARED_AREA_NUM_G))
		{
			hdl->position_value = area_code_sum;		
		}
		
		else
		{
			hdl->position_value = hdl->valid_value.half.trueform;		
		}
	}
	
	else
	{
		hdl->position_value = hdl->valid_value.half.trueform;
	}
	
	#endif
	
	uint8_t area_code_sum = 0;
	
	#if 0
	area_code_sum = (hdl->valid_value.half.trueform |    \
		hdl->trueform_history[1] | hdl->trueform_history[0] | hdl->trueform_history[2] | hdl->trueform_history[3]);
	#elif 1
	
	area_code_sum = (hdl->valid_value.half.trueform | hdl->trueform_history[1] | hdl->trueform_history[0]);
	
	#else
	
	area_code_sum = hdl->valid_value.half.trueform;
	
	#endif
	
	if((area_code_sum == INFRARED_AREA_NUM_E) || (area_code_sum == INFRARED_AREA_NUM_K))
	{
		hdl->position_value = INFRARED_AREA_NUM_B;		
	}
	
	else if((area_code_sum == INFRARED_AREA_NUM_G) || (area_code_sum == INFRARED_AREA_NUM_J))
	{
		hdl->position_value = INFRARED_AREA_NUM_C;
	}
	
	else if(area_code_sum == INFRARED_AREA_NUM_H)
	{
		hdl->position_value = INFRARED_AREA_NUM_F;		
	}
	
	else if(area_code_sum == INFRARED_AREA_NUM_I)
	{
		hdl->position_value = INFRARED_AREA_NUM_F;
	}
	
	else
	{
		hdl->position_value = hdl->valid_value.half.trueform;		
	}
	
	hdl->trueform_history[3] = hdl->trueform_history[2];
	hdl->trueform_history[2] = hdl->trueform_history[1];
	hdl->trueform_history[1] = hdl->trueform_history[0];
	hdl->trueform_history[0] = hdl->valid_value.half.trueform;
	
	hdl->timestamp_old = hdl->timestamp_now;

	return hdl->position_value;

}

/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

int8_t infrared_data_analysis(STR_INFRARED *hdl)
{
	
	for(uint8_t i=0; i<INFRARED_DATA_LENGTH; i++)
	{			
		if(hdl->pulse_value[i] == PULSE_INVALID)
		{
			hdl->pulse_cnt = 0;
			return -1;
		}
	}
	
	hdl->valid_value.bit.receive_x1 = hdl->pulse_value[1];
	hdl->valid_value.bit.receive_x2 = hdl->pulse_value[2];
	hdl->valid_value.bit.receive_x3 = hdl->pulse_value[3];
	hdl->valid_value.bit.receive_x4 = hdl->pulse_value[4];
	hdl->valid_value.bit.receive_x5 = hdl->pulse_value[5];
	hdl->valid_value.bit.receive_x6 = hdl->pulse_value[6];
	hdl->valid_value.bit.receive_x7 = hdl->pulse_value[7];
	hdl->valid_value.bit.receive_x8 = hdl->pulse_value[8];
	
	uint8_t rec_truefrom = hdl->valid_value.half.trueform;
	uint8_t rec_compfrom = hdl->valid_value.half.compform;
	
	if((rec_truefrom == 0x06) && (rec_compfrom == 0x0F))
	{
		hdl->pulse_cnt = 0;
		return 1;
	}
	
	else if(rec_truefrom != ((~rec_compfrom) & 0x0F))
	{
		hdl->pulse_cnt = 0;
		return -1;		
	}		
	
	hdl->pulse_cnt = 0;
	return 1;
	
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void infrared_position_check(void)
{
	int8_t data_result = 0;
	
	for(uint8_t i=0; i<4; i++)
	{
		if(infraredHdl[i].sample_finish == 1)
		{
			data_result = infrared_data_analysis(&infraredHdl[i]);
			
			if(data_result == 1)
			{
				infraredHdl[i].timestamp_now = get_system_runingtime();
				
				#if 0
				userHdl.signal.chargeSignal[i] = infraredHdl[i].valid_value.half.trueform;
				#else
				userHdl.signal.chargeSignal[i] = infrared_area_analysis(&infraredHdl[i]);
				#endif
			}
			
			else if(data_result == -1)
			{
				infraredHdl[i].valid_value.half.trueform = INFRARED_AREA_ERRO;
			}
			
			infraredHdl[i].holdcnt = 0;
			infraredHdl[i].sample_finish = 0;
		}
		else
		{
			infraredHdl[i].holdcnt++;
			
			if(infraredHdl[i].holdcnt > INFRARED_SIGNAL_HOLD_TIME)
			{
				userHdl.signal.chargeSignal[i] = INFRARED_AREA_NULL;
				infraredHdl[i].holdcnt = INFRARED_SIGNAL_HOLD_TIME;
				
				infraredHdl[i].valid_value.half.trueform = INFRARED_AREA_NULL;
				
			}
		}
	}
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void infrared_pulse_store(STR_INFRARED *hdl, int16_t timer_cnt_erro)
{
	ENUM_INFRARED pulse_value;
	
	pulse_value = pulse_value_identify(timer_cnt_erro);
	
	if(pulse_value == BOOT_CODE)
	{
		hdl->pulse_cnt = 0;
		hdl->sample_start = 1;
		hdl->pulse_width[hdl->pulse_cnt] = timer_cnt_erro;
		hdl->pulse_value[hdl->pulse_cnt] = BOOT_CODE;
		hdl->pulse_cnt++;
	}
	
	else if((hdl->sample_start == 1) && (hdl->pulse_cnt != 0))
	{
		
		hdl->pulse_width[hdl->pulse_cnt] = timer_cnt_erro;
		hdl->pulse_value[hdl->pulse_cnt] = pulse_value;
		hdl->pulse_cnt++;
		
		if(hdl->pulse_cnt >= INFRARED_DATA_LENGTH)
		{
			hdl->sample_start = 0;
			hdl->sample_finish = 1;
			hdl->pulse_cnt = 0;
		}		
	}
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void TIMER6_IRQHandler(void)
{

	timer_flag_clear(TIMER6,TIMER_FLAG_UP);

}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void infrared_exti_callback(STR_INFRARED *hdl, FlagStatus level)
{
	uint16_t timer_cnt_erro = 0;
	
	if(level == RESET)
	{
		hdl->timercnt[0] = timer_counter_read(TIMER6);
	}
	
	else
	{
		hdl->timercnt[1] = timer_counter_read(TIMER6);
		
		timer_cnt_erro = (60000 + hdl->timercnt[1] - hdl->timercnt[0]) % 60000;
		
		infrared_pulse_store(hdl, timer_cnt_erro);
	}	
}	



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void EXTI2_IRQHandler(void)
{
	FlagStatus gpio_level;
	
	exti_interrupt_flag_clear(EXTI_2); 
	
	gpio_level = READ_INFRARED_X1;
		
	infrared_exti_callback(&infraredHdl[0], gpio_level);
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void EXTI3_IRQHandler(void)
{
	FlagStatus gpio_level;
	
	exti_interrupt_flag_clear(EXTI_3); 
	
	gpio_level = READ_INFRARED_X2;
		
	infrared_exti_callback(&infraredHdl[1], gpio_level);
}

/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void EXTI4_IRQHandler(void)
{
	FlagStatus gpio_level;
	
	exti_interrupt_flag_clear(EXTI_4); 
	
	gpio_level = READ_INFRARED_X3;
		
	infrared_exti_callback(&infraredHdl[2], gpio_level);
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void EXTI5_9_IRQHandler(void)
{

	FlagStatus gpio_level;
	
	exti_interrupt_flag_clear(EXTI_5); 

	gpio_level = READ_INFRARED_X4;
		
	infrared_exti_callback(&infraredHdl[3], gpio_level);

	
}

